﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Flurl.Http;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO;
using Pay.DTO.jwuct;
using Pay.IService;
using Pay.TO;

namespace Pay.Service {
	public class JwuctPayService : ServiceBase2, IPayService, IDisposable {
		private IUnitOfWork _iUnitOfWork;
		private ISettingService _iSettingService;
		private IMerchantService _iMerchantService;
		private IChargeService _iChargeService;
		private IRefundService _iRefundService;
		private ITransferService _iTransferService;
		private IProfitDayService _iProfitDayService;
		private IBillService _iBillService;
		private IPayHtmlService _iPayHtmlService;
		private JwuctSign _jwuctSign;

		public JwuctPayService(IUnitOfWork iUnitOfWork, ISettingService iSettingService,
						   		IMerchantService iMerchantService, IChargeService iChargeService, IRefundService iRefundService,
								ITransferService iTransferService, IProfitDayService iProfitDayService, IBillService iBillService,
							  	IPayHtmlService iPayHtmlService) : base(iUnitOfWork) {
			_iUnitOfWork = iUnitOfWork;
			_iSettingService = iSettingService;
			_iMerchantService = iMerchantService;
			_iChargeService = iChargeService;
			_iRefundService = iRefundService;
			_iTransferService = iTransferService;
			_iProfitDayService = iProfitDayService;
			_iBillService = iBillService;
			_iPayHtmlService = iPayHtmlService;
			_jwuctSign = new JwuctSign();
		}

		#region 扫码的
		/// <summary>
		/// 生成二维码扫码请求通道封装
		/// </summary>
		/// <returns>The pay gateway.</returns>
		/// <param name="model">Model.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		public async Task<native_result> NativePay(native_model model) {
			var setting = _iSettingService.Get();
			//把商户请求转为通道请求消息
			jwuct_native pay_model = new jwuct_native {
				attach_content = "", messageid = "000014", nonce_str = model.nonce, out_trade_no = model.order_no, product_desc = model.subject,
				notify_url = setting.site.api_url + "/jwuct_native_notify", pay_type = (model.pay_code == "WXPAY" ? "10" : "20"), total_fee = model.tran_amount
			};
			pay_model.sign = _jwuctSign.Sign(pay_model);
			//调用通道执行并处理返回，请通道响应消息封装为平台响应商户消息
			var pay_rep = await _jwuctSign.PayGateway<jwuct_native_result>(pay_model);
			if (pay_rep != null && pay_rep.resultCode == "00" && pay_rep.resCode == "00") {
				//创建订单
				model.transaction_no = "";
				_iChargeService.AddByNativePay(model);
				var data = new native_result {
					order_no = model.order_no, code_url = pay_rep.payUrl
				};
				return await ApiResultToJson.JsonAsync("生成成功", data);
			}
			return await ApiResultToJson.JsonAsync<native_result>("支付失败");
		}
		#endregion

		#region 支付异步通知
		/// <summary>
		/// 回调支付通知，商户返回OK，不再回调了，流程是先调用ChargeService的NotifyOrder，
		/// 返回值判断是调用哪个通道，再调用本方法，最后调用ChargeService的Update
		/// </summary>
		/// <returns>The notify.</returns>
		/// <param name="order_no">Order.</param>
		public async Task<string> Notify(string merchant_no, string order_no) {
			string result = string.Empty;
			charge_dto order = _iChargeService.Get(merchant_no, order_no);
			if (order == null) return "OK";
			try {
				var data = new pay_notity {
					tran_amount = ((int)(order.order_amount * 100)).ToString(), order_no = order.order_no, transaction_no = order.pay_info.transaction_no,
					pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
					status = (order.status == ChargeStatus.Finish ? 1 : 2)
				};
				//失败的要再查询通道判断是否真失败,处理掉单
				if (order.status != ChargeStatus.Finish) {
					var pay_model = new jwuct_head { messageid = "100001", out_trade_no = order.order_no, nonce_str = DtoHelper.GuidTo16String() };
					pay_model.sign = _jwuctSign.Sign(pay_model);
					var hfResult = await _jwuctSign.PayGateway<jwuct_notity>(pay_model);
					if (hfResult != null) {
						if (hfResult.resultCode == "00" && hfResult.resCode == "00") {
							if (hfResult.status == "02") {
								data.status = 1;
								var pay_time = hfResult.createTime.ToDateTime();
								_iChargeService.FailOrUnConfirmToSuceess(merchant_no, order.order_no, pay_time);
							}
						}
					}
				}
				data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
				if (string.IsNullOrEmpty(order.notify)) return "OK";
				var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
				result = notify_result.data;
				var log = IocHelper.Get<ILogHelper>("info");
				log.Info(order.order_no + ":" + notify_result.ToJson());
			} catch (Exception ex) {
				var log = IocHelper.Get<ILogHelper>("info");
				log.Error("订单通道查询异常:" + order.order_no);
				string message = string.Format("消息类型：{0}\r\n消息内容：{1}\r\n引发异常的方法：{2}\r\n引发异常源：{3}"
								, ex.GetType().Name, ex.Message, ex.TargetSite, ex.Source + ex.StackTrace);
				log.Error(message);
			}
			return result;
		}

		/// <summary>
		/// 代付通知－不可用
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="order_no">Order.</param>
		public Task<string> NotifyTransfer(string merchant_no, string order_no) {
			throw new NotImplementedException();
		}
		#endregion

		#region 实名、T0额度-不可用
		/// <summary>
		/// 查询代付T0额度
		/// </summary>
		/// <returns>The quota.</returns>
		/// <param name="merchant_no"></param>
		/// <param name="busiType">0：对公 1：对私</param>
		public Task<quota_result> Quota(string merchant_no, string busiType) {
			throw new NotImplementedException();
		}
		#endregion

		#region 快捷同卡同出
		/// <summary>
		/// 快捷支付查询
		/// </summary>
		/// <returns>The pay query.</returns>
		/// <param name="model">Model.</param>
		public async Task<pay_notity> QuickPayQuery(refund_model_query model) {
			charge_dto order = null;
			var data = new pay_notity { status = 2, order_no = model.order_no };
			if (!string.IsNullOrEmpty(model.order_no)) order = _iChargeService.Get(model.merchant_no, model.order_no);
			if (order == null) {
				var obj = _iPayHtmlService.Get(model.merchant_no, model.order_no);
				if (obj != null) {
					var pay_model = new jwuct_head { messageid = "100001", out_trade_no = obj.order_no, nonce_str = model.nonce };
					pay_model.sign = _jwuctSign.Sign(pay_model);
					var hfResult = await _jwuctSign.PayGateway<jwuct_notity>(pay_model);
					if (hfResult != null) {
						var charge = obj.charge.ToObject<charge_dto>();
						if (hfResult.resultCode == "00" && hfResult.resCode == "00") {
							if (hfResult.status == "02") {
								var pay_time = hfResult.createTime.ToDateTime();
								data.status = 1; data.pay_time = pay_time; data.result_msg = "支付成功"; data.tran_amount = ((int)charge.amount * 100).ToString();
								var result = _iChargeService.PaySuceess(obj, data.order_no, data.pay_time);
								if (result > 0) {
									var notifyResult = await Notify(charge.merchant_no, model.order_no);
									_iPayHtmlService.Remove(obj.id);
								}
							} else {
								data.result_code = 1001; data.result_msg = "支付中";
								data.pay_time = obj.create_time; data.tran_amount = ((int)charge.amount * 100).ToString();
							}
						} else {
							data.result_code = 1001; data.result_msg = "支付失败";
							data.pay_time = obj.create_time; data.tran_amount = ((int)charge.amount * 100).ToString();
						}
					}
				} else {
					data.result_code = 1001; data.result_msg = "支付失败";
				}
			} else {
				data.status = order.status == ChargeStatus.Finish ? 1 : 2; data.pay_time = order.order_time; data.transaction_no = order.order_no;
				data.result_msg = order.status == ChargeStatus.Finish ? "支付成功" : "支付失败"; data.tran_amount = ((int)order.amount * 100).ToString();
				if (order.status != ChargeStatus.Finish) data.result_code = 1001;
			}
			return data;
		}

		/// <summary>
		/// 快捷支付
		/// </summary>
		/// <returns>The receive.</returns>
		/// <param name="model">Model.</param>
		public async Task<quick_pay_result> QuickPay(quick_pay_model model) {
			var setting = _iSettingService.Get();
			var binder = _iMerchantService.Get(model.bind_no);
			string pay_code = model.pay_code;
			model.settle_type = "T0";
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == model.pay_channel);
			var settle = payment.settles.First(c => c.settle_type == model.settle_type && c.code == pay_code);
			//同进件数据比较是否一致
			if (model.settle_fee / 100M != settle.settle)
				return ApiResultToJson.Json<quick_pay_result>("结算费与商户进件的结算费不同", 2001);
			if (model.fee != settle.fee)
				return ApiResultToJson.Json<quick_pay_result>("费率与商户进件的费率不同", 2001);
			if (model.pay_fee_amount != (int)Math.Ceiling(decimal.Parse(model.tran_amount) * model.fee))
				return ApiResultToJson.Json<quick_pay_result>("实扣费率金额不正确");
			//把商户请求转为通道请求消息
			var id = Guid.NewGuid().ToString("N");
			var notify = setting.site.api_url + "/jwuct_back_notify/" + id;
			var front_notify_url = model.front_notify;
			var authinfo = binder.setting.auth_info;
			var pay_model = new jwuct_quick {
				attach_content = "付款", messageid = "000019", nonce_str = model.nonce, out_trade_no = model.order_no, product_desc = "购买商品付款",
				back_notify_url = notify, front_notify_url = front_notify_url, pay_type = "60", bank_name = authinfo.bank_name, bank_num = authinfo.account_no,
				id_name = authinfo.account_name, id_card = authinfo.id_card, pay_bank_num = model.account_no, money = model.tran_amount,
				total_fee = ((int)(model.pay_fee_amount + model.settle_fee)).ToString()
			};
			pay_model.sign = _jwuctSign.Sign(pay_model);
			//调用通道执行并处理返回，请通道响应消息封装为平台响应商户消息
			var html = await _jwuctSign.PayGateway(pay_model);
			if (!string.IsNullOrEmpty(html)) {
				if (html.Substring(0, 4) != "FAIL") {
					var charge = _iChargeService.AddByQuickPay(model);
					//将HTML保存到mongodb
					var ok = _iPayHtmlService.Save(new pay_html_dto { id = id, html = html, merchant_no = model.merchant_no, order_no = model.order_no, charge = charge.ToJson() });
					if (ok) {
						var requestUrl = setting.site.api_url + "/pay/jwuct_front/" + id;
						return ApiResultToJson.Json("鉴权成功，待确认支付", new quick_pay_result {
							order_no = model.order_no, protocol_no = "", request_url = requestUrl,
							pay_time = DateTime.Now, transaction_no = "", status = 3
						});
					} else
						return ApiResultToJson.Json<quick_pay_result>("支付页面加载失败");
				} else
					return ApiResultToJson.Json<quick_pay_result>(html.Substring(3));
			}
			return ApiResultToJson.Json<quick_pay_result>("异常支付");
		}

		/// <summary>
		/// 快捷支付鉴权成功后发短信
		/// </summary>
		/// <returns>The pay resms.</returns>
		/// <param name="model">model.</param>
		public Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 确认短信验证码
		/// </summary>
		/// <returns>The pay.</returns>
		/// <param name="model">model.</param>
		public Task<quick_pay_result> QuickPay(quick_sms_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 快捷支付退款
		/// </summary>
		/// <returns>The pay refund.</returns>
		/// <param name="model">Model.</param>
		public Task<refund_result> QuickPayRefund(refund_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 快捷支付退款查询,并将退款中的单处理为完成
		/// </summary>
		/// <returns>The pay refund.</returns>
		/// <param name="model">Model.</param>
		public Task<refund_result> QuickPayRefundQuery(refund_model_query model) {
			throw new NotImplementedException();
		}
		#endregion

		#region 网关支付-不可用
		/// <summary>
		/// 网关支付银行
		/// </summary>
		/// <returns>The pay bank.</returns>
		public List<type_setting> GatewayPayBank() {
			var banks = new List<type_setting>();
			banks.Add(new type_setting { value = "BOC", text = "中国银行" });
			banks.Add(new type_setting { value = "ABC", text = "中国农业银行" });
			banks.Add(new type_setting { value = "ICBC", text = "中国工商银行" });
			banks.Add(new type_setting { value = "CCB", text = "中国建设银行" });
			banks.Add(new type_setting { value = "COMM", text = "交通银行" });
			banks.Add(new type_setting { value = "PSBC", text = "中国邮政储蓄银行" });
			banks.Add(new type_setting { value = "CMB", text = "招商银行" });
			banks.Add(new type_setting { value = "CMBC", text = "中国民生银行" });
			banks.Add(new type_setting { value = "CITIC", text = "中信银行" });
			banks.Add(new type_setting { value = "CEB", text = "中国光大银行" });
			banks.Add(new type_setting { value = "HXB", text = "华夏银行" });
			banks.Add(new type_setting { value = "GDB", text = "广发银行" });
			banks.Add(new type_setting { value = "CIB", text = "兴业银行" });
			banks.Add(new type_setting { value = "SPDB", text = "上海浦东发展银行" });
			banks.Add(new type_setting { value = "SPAB", text = "平安银行" });
			banks.Add(new type_setting { value = "SHB", text = "上海银行" });
			banks.Add(new type_setting { value = "BJB", text = "北京银行" });
			banks.Add(new type_setting { value = "HZCB", text = "杭州银行" });
			return banks;
		}

		/// <summary>
		/// 发起网关支付
		/// </summary>
		/// <returns>The receive.</returns>
		/// <param name="model">Model.</param>
		public Task<gateway_pay_result> GatewayPay(gateway_pay_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 网关支付查询
		/// </summary>
		/// <returns>The pay query.</returns>
		/// <param name="model">Model.</param>
		public Task<pay_notity> GatewayPayQuery(refund_model_query model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 网关支付退款
		/// </summary>
		/// <returns>The pay refund.</returns>
		/// <param name="model">Model.</param>
		public Task<refund_result> GatewayPayRefund(refund_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 网关支付退款查询,并将退款中的单处理为完成
		/// </summary>
		/// <returns>The pay refund.</returns>
		/// <param name="model">Model.</param>
		public Task<refund_result> GatewayRefundQuery(refund_model_query model) {
			throw new NotImplementedException();
		}
		#endregion

		#region 代付,T+0转账-不可用
		/// <summary>
		/// 单笔代付
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="model">Model.</param>
		public Task<transfer_result> Transfer(apply_transfer model) {
			throw new NotImplementedException();
		}
		public Task<transfer_result> ReTransfer(long id) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 代付批处理:生成代付文件，将批号写入提现表，生成代付文件记录，并上传FTP，FTP成功调用代付通知，FTP失败提示手动上传，并去文件记录管理手动代付通知。
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="model">Model.</param>
		public Task<batch_transfer_result> Transfer(batch_transfer model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 提交代付批处理报盘通知（平台后台用）
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="batchId">Batch Id.</param>
		public Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 提交代付批处理查询，返回回盘文件地址后，进行提现记录更新（平台后台用）
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="batchId">Batch Id.</param>
		/// <param name="noticeTranId">报盘通知交易流水号</param>
		public Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 单笔代付查询
		/// </summary>
		/// <returns>The query.</returns>
		/// <param name="model">Model.</param>
		public Task<transfer_result> TransferQuery(transfer_query model) {
			throw new NotImplementedException();
		}
		#endregion

		#region 代收,T+1转账-不可用
		/// <summary>
		/// 代收签约
		/// </summary>
		/// <returns>The receive.</returns>
		/// <param name="model">Model.</param>
		public Task<ApiResultMessage> InsteadReceive(verify_model model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 代收签约
		/// </summary>
		/// <returns>The receive.</returns>
		/// <param name="model">Model.</param>
		public Task<ApiResultMessage> InsteadReceive(verify_model_sms model) {
			throw new NotImplementedException();
		}

		/// <summary>
		/// 单笔代收
		/// </summary>
		/// <returns>The transfer.</returns>
		/// <param name="model">Model.</param>
		public Task<transfer_result> AgencyFund(apply_receive model) {
			throw new NotImplementedException();
		}
		#endregion

		#region 商户进件-不可用
		public Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type,PayChannel channel = PayChannel.None) {
			throw new NotImplementedException();
		}

		public Task<merchant_register_result> MerchantModify(long bind_id, string settle_type,PayChannel channel = PayChannel.None) {
			throw new NotImplementedException();
		}

		public Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt) {
			throw new NotImplementedException();
		}
		#endregion

		#region 对账
		public async Task<int> ItpToFile(DateTime create_date) {
			var trans_date = create_date.ToString("yyyyMMdd");
			string batchFileName = trans_date + ".txt";
			var fileName = IOHelper.GetMapPath("JWUCT", trans_date, batchFileName);
			var result = _iProfitDayService.Insert(new profit_day_dto {
				create_date = create_date, file = batchFileName, status = 1, pay_channel = PayChannel.HxData
			});
			return await Task.FromResult( result);
		}

		public int DealItp(long id) {
			throw new NotImplementedException();
		}

		public Task<certify_verify_result> CertifyVerify(certify_verify model) {
			throw new NotImplementedException();
		}

		public Task<mall_result> MallPay(mall_model obj) {
			throw new NotImplementedException();
		}

        public Task<transfer_result> TokenTransfer(long id) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model) {
            throw new NotImplementedException();
        }
        #endregion
    }
}
